package com.gitee.mrj.aiboot.core.sf.generators.type;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.gitee.mrj.aiboot.annotation.config.sf.type.AlainArray;
import com.gitee.mrj.aiboot.core.sf.generators.FormDefinitionGenerator;
import com.gitee.mrj.aiboot.core.sf.generators.UIForm;
import com.gitee.mrj.aiboot.core.sf.schema.UiFormSchemaGenerator;
import com.gitee.mrj.aiboot.core.util.ReflectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

@Component
public class AlainArrayGenerator implements FormDefinitionGenerator {
    private static final Logger LOGGER = LoggerFactory.getLogger(AlainArrayGenerator.class);

    @Override
    public void generate(UIForm root, Field field, UIForm node) {
        if (node.getLevel() > 2) {
            return;
        }
        AlainArray alainField = AnnotatedElementUtils.findMergedAnnotation(field, AlainArray.class);
        ObjectNode fieldFormDefinition = node.getSchema();
        node.getUi().put("widget", "array");
        try {
            fieldFormDefinition.put("type", SFSchemaType.ARRAY.toString());
            putInt(fieldFormDefinition, "maxItems", alainField.maxItems());
            putInt(fieldFormDefinition, "minItems", alainField.minItems());
            fieldFormDefinition.put("uniqueItems", alainField.uniqueItems());

            ObjectNode arraySchema = fieldFormDefinition.putObject("items");
            ObjectNode ui = node.getUi();

            UIForm itemFrom = new UIForm(node.getMapper(), arraySchema, ui, node.getLevel());

            Class clazz = ReflectionUtils.getResolvableType(field);

            UiFormSchemaGenerator.buildProperties(clazz, itemFrom);
            List<Field> fields = ReflectionUtils.findAllAlainFields(clazz);
            UiFormSchemaGenerator.buildOrder(fields, ui);
            Map<Field, UIForm> nodeMap = UiFormSchemaGenerator.initFieldsFormDefinition(itemFrom, fields);
            ObjectNode properties = arraySchema.putObject("properties");
            ObjectNode itemUi = ui.putObject("$items");
            arraySchema.put("type", SFSchemaType.OBJECT.toString());
            nodeMap.forEach((key, form) -> {
                properties.set(key.getName(), form.getSchema());
                if (form.getUi().size() > 0) {
                    itemUi.set("$" + key.getName(), form.getUi());
                }
            });
        } catch (Exception e) {
            LOGGER.error("数组类型有误，请检查！", e);
        }
    }


    @Override
    public void generate(UIForm root, Class clazz) {
        ObjectNode schema = root.getSchema();
        AlainArray alainField = AnnotatedElementUtils.findMergedAnnotation(clazz, AlainArray.class);
        root.getUi().put("widget", SFSchemaType.ARRAY.toString());
        schema.put("title", alainField.title());
        if (StringUtils.isNotBlank(alainField.description())) {
            schema.put("description", alainField.description());
        }
    }

    @Override
    public Class[] supports() {
        return new Class[]{AlainArray.class};
    }

}
